#include	"CenterConnector.h"
#include	"LoginService.h"

#include	<protocols/Common.pb.h>
#include	<protocols/Center.pb.h>
#include	<protocols/Login.pb.h>

void CenterConnector::OnConnected() {
	IBaseConnector::OnConnected();

	/** Register self on center */
	Proto::CmdRegister reg;
	reg.set_type(Proto::ST_LOGIN);
	reg.mutable_addr()->set_ip("");
	reg.mutable_addr()->set_port(0);
	Send(Proto::CMD_REGISTER, reg);
}

void CenterConnector::OnReceive(Protocol * msg) {
	int pf = msg->pf;
	uint32_t serial = msg->serial;

	if (pf == Proto::RSP_VERIFY) {
		auto reply = Cast<Proto::Center::RspVerify>(msg);
		if (!reply) return;

		std::string account = reply->account();
		auto client = LoginService::Instance().Unlink(account);
		if (!client) return;

		Proto::Login::RspVerify rsp;
		rsp.set_status(reply->status());
		rsp.set_account(account);
		rsp.set_session(reply->session());

		if (rsp.status() == Proto::S_Success) {
			rsp.mutable_addr()->CopyFrom(reply->addr());
			rsp.mutable_roles()->CopyFrom(reply->roles());
		}

		client->Reply(pf, rsp, serial);
	} else if (pf == Proto::RSP_CREATEROLE) {
		auto reply = Cast<Proto::Center::RspCreate>(msg);
		if (!reply) return;

		std::string account = reply->account();
		auto client = LoginService::Instance().Unlink(account);
		if (!client) return;

		Proto::Login::RspCreate rsp;
		rsp.set_status(reply->status());

		if (rsp.status() == Proto::S_Success) {
			rsp.mutable_role()->CopyFrom(reply->role());
		}

		client->Reply(pf, rsp, serial);
	} else {
		LOG_ERR("[center]Received unsupported message. PF : %d", pf);
	}
}

void CenterConnector::Verify(const std::string & account, uint32_t sid, const std::string & code, uint32_t serial) {
	Proto::Center::ReqVerify req;
	req.set_account(account);
	req.set_code(code);
	req.set_sid(sid);
	
	if (!Send(Proto::REQ_VERIFY, req, serial, true)) {
		Sender * client = LoginService::Instance().Unlink(account);
		LoginService::Instance().FailedVerify(client, Proto::S_ENetwork, serial, true);
	}
}

void CenterConnector::Create(const std::string & account, const std::string & session, uint32_t sid, const std::string & name, uint32_t serial) {
	Proto::Center::ReqCreate req;
	req.set_account(account);
	req.set_session(session);
	req.set_sid(sid);
	req.set_name(name);

	if (!Send(Proto::REQ_CREATEROLE, req, serial)) {
		Sender * client = LoginService::Instance().Unlink(account);
		LoginService::Instance().FailedCreate(client, Proto::S_ENetwork, serial);
	}
}